local commanders_desc = [[
统率模式
]]

local commanders_getLogic = function()
  local commanders_logic = GameLogic:subclass("commanders_logic") ---@class GameLogic

  function commanders_logic:initialize(room)
    GameLogic.initialize(self, room)
    self.role_table = {
      { "cool_vanguard", "cool_marshal", "cool_vanguard", "warm_vanguard", "warm_marshal", "warm_vanguard" },
    }
    -- 设置房间的luckTime为0（手气卡数量为0）
    self.room.settings.luckTime = 0
    -- 设置出牌超时时间为24小时
    self.room.timeout = 86400
  end

  function commanders_logic:assignRoles()
    -- 定义一个函数，获取除了指定玩家p以外的所有玩家
    local function getOtherPlayers(room, p)
      local ret = table.simpleClone(room.players) -- 克隆玩家列表
      table.removeOne(ret, p)                     -- 移除指定玩家p
      return ret                                  -- 返回剩余玩家
    end

    local function getalivePlayers(room)
      local ret = table.simpleClone(room.players) -- 克隆玩家列表
      return ret                                  -- 返回剩余玩家
    end

    -- 定义一个函数，通过屏幕名查找玩家对象
    local function getPlayerByScreenName(room, name)
      return table.find(room.players, function(p)
        return p._splayer:getScreenName() == name -- 匹配屏幕名
      end)
    end

    local room = self.room                                            -- 获取当前房间对象
    local croom = room.room                                           -- 获取上层房间对象
    local cowner = croom:getOwner()                                   -- 获取上层房间的房主
    local owner = getPlayerByScreenName(room, cowner:getScreenName()) -- 通过屏幕名找到当前房间的房主
    -- 让房主选择一名角色当冷主
    local cm = room:askForChoosePlayers(owner, table.map(getalivePlayers(room), Util.IdMapper),
      1, 1, "#commanders_choose_cm", "", false)
    cm = room:getPlayerById(cm[1])
    -- local cm = room:askToChoosePlayers(owner, {
    --   targets = room:getAllPlayers(),
    --   min_num = 1,
    --   max_num = 1,
    --   prompt = "#commanders_choose_cm",
    --   skill_name = "commanders_gamerule",
    --   cancelable = false
    -- })


    -- 让房主选择一名角色当暖主
    local wm = room:askForChoosePlayers(owner, table.map(getOtherPlayers(room, cm), Util.IdMapper),
      1, 1, "#commanders_choose_wm", "", false)
    wm = room:getPlayerById(wm[1])
    -- local wm = room:askToChoosePlayers(owner, {
    --   targets = room:getOtherPlayers(cm),
    --   min_num = 1,
    --   max_num = 1,
    --   prompt = "#commanders_choose_wm",
    --   skill_name = "commanders_gamerule",
    --   cancelable = false
    -- })

    if cm and wm then
      -- 定义一个对位表，确定房主和队友的座位
      -- local cm_table = { 6, 5, 4, 3, 2, 1 }
      local wm_seat = 5
      local cm_seat = 2
      local others = getOtherPlayers(room, wm)
      table.removeOne(others, cm)
      table.shuffle(others)
      local players = {}
      players[wm_seat] = wm
      players[cm_seat] = cm
      players[1] = others[1]
      players[3] = others[2]
      players[4] = others[3]
      players[6] = others[4]
      room.players =
          players                                                                                                        -- 更新房间玩家顺序
    else
      table.shuffle(room.players)                                                                                        -- 随机打乱玩家顺序
    end                                                                                                                  -- 玩家数量

    local roles = { "cool_vanguard", "cool_marshal", "cool_vanguard", "warm_vanguard", "warm_marshal", "warm_vanguard" } -- 预设角色顺序

    for i = 1, #room.players do
      local p = room.players[i]
      p.role = roles[i] -- 给每个玩家分配角色
      room:setPlayerProperty(p, "role_shown", true)
      room:broadcastProperty(p, "role")
    end

    -- 设置1、2、3号玩家互为队友
    room.players[1]:addBuddy(room.players[2])
    room.players[1]:addBuddy(room.players[3])
    room.players[2]:addBuddy(room.players[1])
    room.players[2]:addBuddy(room.players[3])
    room.players[3]:addBuddy(room.players[1])
    room.players[3]:addBuddy(room.players[2])

    -- 设置4、5、6号玩家互为队友
    room.players[4]:addBuddy(room.players[5])
    room.players[4]:addBuddy(room.players[6])
    room.players[5]:addBuddy(room.players[4])
    room.players[5]:addBuddy(room.players[6])
    room.players[6]:addBuddy(room.players[4])
    room.players[6]:addBuddy(room.players[5])

    -- self.start_role = roles[1] -- 记录起始角色
    -- -- 为调整座位做准备，将第一个玩家的角色设为“lord”
    -- room.players[1].role = "lord"
    -- 设置第一个玩家为当前玩家
    room:setCurrent(room.players[1])
  end

  function commanders_logic:chooseGenerals()
    local room = self.room                                             -- 获取当前房间对象
    math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 6))) -- 用当前时间的倒序前6位初始化随机种子

    local cool_marshal = room.players[2]                               -- 冷方主将为2号玩家
    local warm_marshal = room.players[5]                               -- 暖方主将为5号玩家
    room:setCurrent(cool_marshal)                                      -- 设置当前操作玩家为冷方主将

    -- 定义武将池，包含多个年份的武将名
    local general_pool = {}
    local trueNames = {} -- 用于记录已存在的武将真名
    for _, name in ipairs(room.general_pile) do
      if not trueNames[name] then
        trueNames[name] = true -- 标记已存在的武将名
      end
    end
    for _, general in ipairs(general_pool) do
      -- 如果武将存在且其真名未被记录，则加入武将池
      if Fk.generals[general] and not trueNames[Fk.generals[general].trueName] then
        table.insert(room.general_pile, general)        -- 加入未在白名单内的trueName
        trueNames[Fk.generals[general].trueName] = true -- 标记为已存在
      end
    end
    table.shuffle(room.general_pile)           -- 随机打乱武将池
    local all_generals = room:getNGenerals(16) -- 从武将池中抽取16个武将
    if #all_generals < 16 then
      room:sendLog {
        type = "#NoGeneralDraw", -- 日志：没有足够的武将
        toast = true,
      }
      room:gameOver("") -- 结束游戏
    end

    local cool_generals, warm_generals = {}, {} -- 冷方、暖方已选武将
    local cool_selected, warm_selected = {}, {} -- 冷方、暖方已选武将索引

    -- 更新武将池显示
    local updataGeneralPile = function(p)
      if p == cool_marshal then
        room:setBanner("@&cool_generals", cool_generals)
      else
        room:setBanner("@&warm_generals", warm_generals)
      end
    end

    -- 选择武将的函数
    local function chooseGeneral(p, n)
      -- 构造选择提示字符串，区分冷方和暖方主将，并带上选择数量
      local prompt = "#commanders_mode-choose:::" .. (p == cool_marshal and "firstPlayer" or "secondPlayer") .. ":" .. n
      -- 根据当前玩家身份，确定自己的已选索引表
      local my_selected = (p == cool_marshal) and cool_selected or warm_selected
      -- 根据当前玩家身份，确定对方的已选索引表
      local ur_selected = (p == cool_marshal) and warm_selected or cool_selected
      -- 根据当前玩家身份，确定自己的已选武将表
      local my_genrals = (p == cool_marshal) and cool_generals or warm_generals

      -- 弹出自定义对话框让玩家选择武将，传递所有武将、选择数量、双方已选索引和提示
      local result = room:askToCustomDialog(p, {
        skill_name = "game_rule",
        qml_path = "packages/gamemode/qml/1v1.qml",
        extra_data = {
          all_generals, n, my_selected, ur_selected, prompt
        }
      })

      local selected = {}               -- 用于记录本次选择的武将
      if result ~= "" then
        result = json.decode(result)    -- 解析选择结果（json字符串转表）
        for i, id in ipairs(result.ids) do
          local g = result.generals[i]  -- 获取选择的武将名
          all_generals[id + 1] = g      -- 用新武将替换原位置
          table.insert(my_selected, id) -- 记录已选索引
          table.insert(my_genrals, g)   -- 记录已选武将
          table.insert(selected, g)     -- 记录本次选择
        end
      else
        -- 如果玩家未主动选择，则自动分配未被选中的武将
        local selected_list = table.connect(my_selected, ur_selected) -- 合并双方已选索引
        for i, g in ipairs(all_generals) do
          if not table.contains(selected_list, i - 1) then            -- 如果该武将未被选中
            table.insert(my_selected, i - 1)                          -- 记录索引
            table.insert(my_genrals, g)                               -- 记录武将
            table.insert(selected, g)                                 -- 记录本次选择
            if #selected == n then break end                          -- 达到所需数量则停止
          end
        end
      end
      -- 发送选择日志，记录本次选择
      room:sendLog {
        type = "#commandersChooseGeneralsLog",
        arg = p == cool_marshal and "cool" or "warm", -- 标记冷方或暖方
        arg2 = selected[1],                           -- 第一个选择的武将
        arg3 = selected[2] or "",                     -- 第二个选择的武将（可能没有）
        toast = true,                                 -- 弹出提示
      }
      updataGeneralPile(p)                            -- 更新武将池显示
    end

    -- 先让暖色主帅查看所有武将
    room:sendLog {
      type = "#CommandersShowGenerals",
      toast = true,
    }

    -- 显示所有待选武将给暖色主帅
    local result = room:askToCustomDialog(warm_marshal, {
      skill_name = "game_rule",
      qml_path = "packages/gamemode/qml/1v1.qml",
      extra_data = {
        all_generals, 0, {}, {}, "#commanders_preview_generals"
      }
    })

    -- 让暖色主帅选择是否交换选将顺序
    local choices = { "warm_first", "cool_first" }
    local choice = room:askToChoice(warm_marshal, {
      choices = choices,
      skill_name = "game_rule",
      prompt = "#commanders_choose_order",
    })

    -- 发送选择顺序的日志
    room:sendLog {
      type = "#CommandersChooseOrder",
      arg = choice == "warm_first" and "warm" or "cool",
      toast = true,
    }

    -- 根据暖色主帅的选择确定选将顺序
    if choice == "warm_first" then
      -- 原来的顺序：暖方先选
      chooseGeneral(warm_marshal, 1)
      chooseGeneral(cool_marshal, 2)
      chooseGeneral(warm_marshal, 2)
      chooseGeneral(cool_marshal, 2)
      chooseGeneral(warm_marshal, 2)
      chooseGeneral(cool_marshal, 2)
      chooseGeneral(warm_marshal, 2)
      chooseGeneral(cool_marshal, 2)
      chooseGeneral(warm_marshal, 1)
    else
      -- 新的顺序：冷方先选
      chooseGeneral(cool_marshal, 1)
      chooseGeneral(warm_marshal, 2)
      chooseGeneral(cool_marshal, 2)
      chooseGeneral(warm_marshal, 2)
      chooseGeneral(cool_marshal, 2)
      chooseGeneral(warm_marshal, 2)
      chooseGeneral(cool_marshal, 2)
      chooseGeneral(warm_marshal, 2)
      chooseGeneral(cool_marshal, 1)
    end
    -- 创建请求，让双方主将从各自已选武将中选择3个
    local req = Request:new({ cool_marshal, warm_marshal }, "AskForGeneral")
    req:setData(cool_marshal, { cool_generals, 3, true })
    req:setDefaultReply(cool_marshal, table.random(cool_generals, 3))
    req:setData(warm_marshal, { warm_generals, 3, true })
    req:setDefaultReply(warm_marshal, table.random(warm_generals, 3))

    -- 广播提示信息
    room:doBroadcastNotify("ShowToast", Fk:translate("commanders_choose_general"), { cool_marshal, warm_marshal })
    req:ask()                            -- 等待双方主将选择

    room:setBanner("@&cool_generals", 0) -- 清除冷方武将池显示
    room:setBanner("@&warm_generals", 0) -- 清除暖方武将池显示

    local generals = {}                  -- 最终选中的6名武将
    table.insertTable(generals, req:getResult(cool_marshal))
    table.insertTable(generals, req:getResult(warm_marshal))

    -- 给每个玩家分配武将，并广播
    for i = 1, 6, 1 do
      local p = room.players[i]
      room:setPlayerGeneral(p, generals[i], true, true)
      room:broadcastProperty(p, "general")
    end
  end

  function commanders_logic:attachSkillToPlayers()
    local room = self.room
    local addRoleModSkills = function(player, skillName)
      local skill = Fk.skills[skillName]
      if not skill then
        fk.qCritical("Skill: " .. skillName .. " doesn't exist!")
        return
      end
      if skill:hasTag(Skill.Lord) then
        return
      end
      if skill:hasTag(Skill.AttachedKingdom) and not table.contains(skill:getSkeleton().attached_kingdom, player.kingdom) then
        return
      end

      room:handleAddLoseSkills(player, skillName, nil, false)
    end
    for _, p in ipairs(room.alive_players) do
      for _, s in ipairs(Fk.generals[p.general]:getSkillNameList(false)) do
        addRoleModSkills(p, s)
      end
      if p.deputyGeneral ~= "" then
        for _, s in ipairs(Fk.generals[p.deputyGeneral]:getSkillNameList(false)) do
          addRoleModSkills(p, s)
        end
      end
    end
  end

  ---@class commanders_Round: GameEvent.Round
  local commanders_Round = GameEvent.Round:subclass("commanders_Round") -- 定义commanders_Round类，继承自GameEvent.Round

  function commanders_Round:action()
    local room = self.room        -- 获取当前房间对象
    local logic = self.room.logic -- 获取游戏逻辑对象

    -- 查找冷方主将玩家
    local cool_marshal = table.find(room.players, function(p)
      return p.role == "cool_marshal"
    end)
    -- 查找暖方主将玩家
    local warm_marshal = table.find(room.players, function(p)
      return p.role == "warm_marshal"
    end)

    -- 为所有玩家清除行动标记
    for _, p in ipairs(room.alive_players) do
      room:setPlayerMark(p, "@!action-round", 0)
    end

    -- 检查是否需要应用保护规则（交换行动顺序）
    local should_swap_order = false

    -- 查找带有"@last_action"标记的角色（上一轮最后行动的阵营的主帅）
    local last_actor = table.find(room.alive_players, function(p)
      return p:getMark("@last_action") > 0
    end)

    if last_actor then
      -- 确定上一个行动角色的阵营
      local last_active_camp = string.sub(last_actor.role, 1, 4) -- 获取"cool"或"warm"
      -- 确定初始设定的先行指挥阵营
      local initial_first_camp = logic.first_action == "cool_marshal_first" and "cool" or "warm"

      -- 如果上一轮最后行动的阵营与本轮应该先行的阵营相同，则交换顺序
      if last_active_camp == initial_first_camp then
        should_swap_order = true
        -- 发送保护规则生效的日志
        room:sendLog {
          type = "#CommandersProtectionRule",
          arg = initial_first_camp == "cool" and "warm" or "cool",
          toast = true,
        }
      end
    end

    -- 定义主将指挥行动的函数
    local function CommandAction(marshal)
      room = marshal.room
      local friends = table.filter(room.alive_players, function(p)
        return marshal:isFriend(p) and p:getMark("@!action-round") == 0
      end)
      local allNoActionMark = true
      for _, p in ipairs(room.alive_players) do
        if p:getMark("@!action-round") ~= 0 then
          allNoActionMark = false
          break
        end
      end
      local num = room:getBanner("RoundCount")
      if #friends > 0 then
        local to = friends[1]
        if allNoActionMark and num == 1 then
          to = marshal
        elseif #friends > 1 then
          to = room:askToChoosePlayers(marshal, {
            min_num = 1,
            max_num = 1,
            targets = friends,
            skill_name = "game_rule",
            prompt = "#commanders_action",
            cancelable = false,
          })[1]
        end
        room:setCurrent(to)
        room:setPlayerMark(to, "@!action-round", 1)
        GameEvent.Turn:create(TurnData:new(to)):exec()
        room:ActExtraTurn()
        while to ~= marshal do
          if room.game_finished then break end
          local vanguards = table.filter(room.alive_players, function(p)
            return p.role:endsWith("vanguard") and marshal:isFriend(p) and p:getMark("@!action-round") == 0
          end)
          if #vanguards > 0 then
            to = vanguards[1]
            if #vanguards > 1 then
              to = room:askToChoosePlayers(marshal, {
                min_num = 1,
                max_num = 1,
                targets = vanguards,
                skill_name = "game_rule",
                prompt = "#commanders_action",
                cancelable = false,
              })[1]
            end
            room:setCurrent(to)
            room:setPlayerMark(to, "@!action-round", 1)
            GameEvent.Turn:create(TurnData:new(to)):exec()
            room:ActExtraTurn()
          else
            break
          end
        end
      end
    end

    -- 只要还有未行动的玩家就继续轮流指挥
    while table.find(room.alive_players, function(p)
        return p:getMark("@!action-round") == 0
      end) do
      if room.game_finished then break end -- 游戏已结束则跳出

      -- 根据是否应该交换顺序决定谁先行动
      if logic.first_action == "cool_marshal_first" and not should_swap_order or
          logic.first_action == "warm_marshal_first" and should_swap_order then
        CommandAction(cool_marshal) -- 冷方主将指挥
        if room.game_finished then break end
        CommandAction(warm_marshal) -- 暖方主将指挥
      else
        CommandAction(warm_marshal) -- 暖方主将指挥
        if room.game_finished then break end
        CommandAction(cool_marshal) -- 冷方主将指挥
      end
    end
  end

  function commanders_logic:action()
    local room = self.room
    self:trigger(fk.GamePrepared)

    -- 查找冷方主将和暖方主将
    local cool_marshal = table.find(room.players, function(p)
      return p.role == "cool_marshal"
    end)
    local warm_marshal = table.find(room.players, function(p)
      return p.role == "warm_marshal"
    end)

    -- 让冷方主将选择先行动的阵营
    local choices = { "cool_marshal_first", "warm_marshal_first" }
    local choice = room:askToChoice(cool_marshal, {
      choices = choices,
      skill_name = "game_rule",
      prompt = "#commanders_choose_first",
    })
    -- 记录先行动的阵营
    self.first_action = choice

    -- 发送选择日志
    room:sendLog {
      type = "#CommandersChooseFirstAction",
      arg = choice == "cool_marshal_first" and "cool" or "warm",
      toast = true,
    }

    GameEvent.DrawInitial:create():exec()

    while true do
      commanders_Round:create():exec()     -- 执行一个轮次
      if room.game_finished then break end -- 如果游戏结束则跳出循环
    end
  end

  return commanders_logic
end

local commanders_mode = fk.CreateGameMode {
  name = "commanders_mode",
  minPlayer = 6,
  maxPlayer = 6,
  logic = commanders_getLogic,
  rule = "#commanders_rule&",
  surrender_func = function(self, playedTime)
    return { { text = "marshal_surrender", passed = true } }
  end,
  whitelist = {
    "commanders_cards",
    "wzzz_cards",
    "commanders_generals",
    "s15_generals",
  },
  winner_getter = function(self, victim)
    if not victim.surrendered and victim.rest > 0 then
      return ""
    end
    if victim.role == "cool_marshal" then
      return "warm_marshal+warm_vanguard"
    elseif victim.role == "warm_marshal" then
      return "cool_marshal+cool_vanguard"
    end
    return ""
  end,
  get_adjusted = function(self, player)
    if player.role:endsWith("marshal") then
      return { hp = player.hp + 1, maxHp = player.maxHp + 1 }
    end
    return {}
  end,

  reward_punish = function(self, victim, killer)
    if killer and victim.role:endsWith("vanguard") and not killer.dead then
      killer:drawCards(2, "kill")
    end
  end,
  friend_enemy_judge = function(self, targetOne, targetTwo)
    -- 检查targetOne和targetTwo的role是否存在并且不为空
    if not targetOne.role or not targetTwo.role or targetOne.role == "" or targetTwo.role == "" then
      return false
    end

    -- 确保role至少有一个字符才进行比较
    if #targetOne.role > 0 and #targetTwo.role > 0 then
      return targetOne.role[1] == targetTwo.role[1]
    end

    return false
  end,
}

Fk:loadTranslationTable {
  ["commanders_mode"] = "统率",
  [":commanders_mode"] = commanders_desc,
  ["cool"] = "冷色方",
  ["warm"] = "暖色方",
  ["cool_marshal"] = "冷方主帅",
  ["warm_marshal"] = "暖方主帅",
  ["cool_vanguard"] = "冷方先锋",
  ["warm_vanguard"] = "暖方先锋",

  ["#commanders_choose_cm"] = "请选择一名玩家当冷主",
  ["#commanders_choose_wm"] = "请选择一名玩家当暖主",
  ["#commanders_mode-choose"] = "你是[%arg]，请选择 %arg2 张武将牌作为备选",
  ["#commandersChooseGeneralsLog"] = "%arg 选择了 %arg2 %arg3",
  ["#CommandersChooseOrder"] = "暖色方选择了由 %arg 先行选将",
  ["#CommandersShowGenerals"] = "暖色方正在预览武将",
  ["#CommandersChooseFirstAction"] = "冷色方选择了由 %arg 先行指挥",
  ["#commanders_preview_generals"] = "请查看可选的武将牌",
  ["commanders_choose_general"] = "请为本方阵营选择选择武将，从左至右为：左方先锋 主帅 右方先锋",
  ["#commanders_choose_order"] = "请选择选将顺序",
  ["#commanders_choose_first"] = "请选择先行动的阵营",
  ["cool_marshal_first"] = "冷方主帅先行动",
  ["warm_marshal_first"] = "暖方主帅先行动",
  ["warm_first"] = "暖色方先选",
  ["cool_first"] = "冷色方先选",
  ["@&cool_generals"] = "冷方已选武将",
  ["@&warm_generals"] = "暖方已选武将",

  ["#commanders_action"] = "选择一名友方角色行动",

  ["#commanders_aoe-choice"] = "选择你使用%arg结算的方向",
  ["left"] = "←顺时针方向",
  ["right"] = "逆时针方向→",

  ["cool_marshal+cool_vanguard"] = "冷色方",
  ["warm_marshal+warm_vanguard"] = "暖色方",
  ["marshal_surrender"] = "将军走此小道",
  ["@last_action"] = "上次行动方",
  ["#CommandersProtectionRule"] = "%arg保护规则生效",
}

return commanders_mode
